/**
*		@file Uses.cpp
*		@brief Uses class
*
*		@author Kong Ling Ming
*
*		@date 1/25/2012
*/

#include "Uses.h"

vector<UsesEntry*>	Uses::vp_uses_entries_;
vector<VarSet>	Uses::uses_stmt_table_;
vector<StmtSet>	Uses::uses_stmt_table_t_;

vector<VarSet>	Uses::uses_proc_table_;
vector<ProcSet>	Uses::uses_proc_table_t_;

StmtSet			Uses::uses_has_s0_;
ProcSet			Uses::uses_has_p0_;
VarSet			Uses::uses_has_0v_;
bool			Uses::uses_has_00_;

void Uses::SetUsesA(StmtNum stmt_num, VarIdx var_idx)
{
	UsesEntry* p_uses_entriy_temp = new UsesEntry;
	p_uses_entriy_temp->stmt_num=stmt_num;
	p_uses_entriy_temp->var_idx=var_idx;
	vp_uses_entries_.push_back(p_uses_entriy_temp);
}

void Uses::RebuildUses()
{
	uses_stmt_table_.resize(StmtTable::GetSize());
	for( int i = 0; i < StmtTable::GetSize(); i++)
	{
		uses_stmt_table_[i].resize(VarTable::GetSize());
	}

	uses_proc_table_.resize(ProcTable::GetSize());
	for( int i = 0; i < ProcTable::GetSize(); i++)
	{
		uses_proc_table_[i].resize(VarTable::GetSize());
	}

	// copy data from linked list to array
	for(unsigned int i = 0; i < vp_uses_entries_.size(); i++ )
	{
		uses_stmt_table_[vp_uses_entries_[i]->stmt_num-1][vp_uses_entries_[i]->var_idx-1] = true;
	}

	// free memory of linked list
	vp_uses_entries_.clear();

	uses_has_s0_.resize(StmtTable::GetSize());
	uses_has_p0_.resize(ProcTable::GetSize());
	uses_has_0v_.resize(VarTable::GetSize());
	uses_has_00_=false;
	return;

}

void Uses::TransposeUses()
{
	uses_stmt_table_t_.resize(VarTable::GetSize());
	uses_proc_table_t_.resize(VarTable::GetSize());
	for( int i = 0; i < VarTable::GetSize(); i++ )
	{
		uses_stmt_table_t_[i].resize(StmtTable::GetSize());
		uses_proc_table_t_[i].resize(ProcTable::GetSize());
	}

	for( int i = 0; i < VarTable::GetSize(); i++ )
	{
		for( int j = 0; j < StmtTable::GetSize(); j++ )
			uses_stmt_table_t_[i][j] = uses_stmt_table_[j][i];
		for( int j = 0; j < ProcTable::GetSize(); j++ )
			uses_proc_table_t_[i][j] = uses_proc_table_[j][i];
	}
}

void Uses::CompleteUses()
{
	for( int i = 0; i < StmtTable::GetSize(); i++ )		uses_has_s0_[i] = IsAny<VarSet>(uses_stmt_table_[i]);
	for( int i = 0; i < ProcTable::GetSize(); i++ )		uses_has_p0_[i] = IsAny<VarSet>(uses_proc_table_[i]);
	for( int i = 0; i < VarTable::GetSize(); i++ )		uses_has_0v_[i] = IsAny<ProcSet>(uses_proc_table_t_[i]);
	uses_has_00_ = IsAny<VarSet>(uses_has_0v_);
	return;
}

void Uses::SetUsesS(StmtNum stmt_num, VarSet var_set)
{
	uses_stmt_table_[stmt_num-1] = var_set;
}

void Uses::SetUsesP(ProcIdx proc_idx, VarSet var_set)
{
	uses_proc_table_[proc_idx-1] = var_set;
}

VarSet& Uses::GetUsesS(StmtNum stmt_num)
{
	return uses_stmt_table_[stmt_num-1];
}

VarSet& Uses::GetUsesP(ProcIdx proc_idx)
{
	return uses_proc_table_[proc_idx-1];
}

StmtSet& Uses::GetUsesByS(VarIdx var_idx)
{
	return uses_stmt_table_t_[var_idx-1];
}

ProcSet& Uses::GetUsesByP(VarIdx var_idx)
{
	return uses_proc_table_t_[var_idx-1];
}

bool Uses::IsUsesS(StmtNum stmt_num, VarIdx var_idx)
{
	if( stmt_num > StmtTable::GetSize() )
		return false;
	if( stmt_num == 0 )
	{
		if( var_idx == 0 )
			return uses_has_00_;
		else
			return uses_has_0v_[var_idx - 1];
	}
	else
	{
		if( var_idx == 0 )
			return uses_has_s0_[stmt_num - 1];
		else
			return uses_stmt_table_[stmt_num-1][var_idx-1];
	}
}

bool Uses::IsUsesP(ProcIdx proc_idx, VarIdx var_idx)
{
	if( proc_idx == 0 )
	{
		if( var_idx == 0 )
			return uses_has_00_;
		else
			return uses_has_0v_[var_idx - 1];
	}
	else
	{
		if( var_idx == 0 )
			return uses_has_p0_[proc_idx - 1];
		else
			return uses_proc_table_[proc_idx-1][var_idx-1];
	}
}

string Uses::ToString()
{
	stringstream ss_result;

	ss_result << "Uses : " << uses_has_00_ << "\nUses stmt:\n";
	for( int i = 0; i < StmtTable::GetSize(); i++ )
	{
		ss_result << (i+1)  << " [" << uses_has_s0_[i] << "] : ";
		for( int j = 0; j < VarTable::GetSize(); j++ )
			if( uses_stmt_table_[i][j] )

				ss_result << VarTable::GetVarName(j+1) <<" ";
		ss_result << "\n";
	}

	ss_result << "Uses proc:\n";
	for( int i = 0; i < ProcTable::GetSize(); i++ )
	{
		ss_result << (i+1)  << " [" << uses_has_p0_[i] << "] : ";
		for( int j = 0; j < VarTable::GetSize(); j++ )
			if( uses_proc_table_[i][j] )
				ss_result << VarTable::GetVarName(j+1) <<" ";
		ss_result << "\n";
	}

	return ss_result.str();
}

